AWS ChatbotからのLambda起動をCloudFormationとSlackワークフローで使いやすくする
データアナリティクス事業本部、池田です。
少し前にGAされた AWS Chatbot を触ってみました。
Slackワークフローを使うことで、だいぶ使いやすくなりました。
やること
Slackから Chatbotのコマンド を発行することで、 AWS Lambdaを同期で起動 します。
最終的な結果はこんな感じ↓
Lambdaの作成
今回は、Chatbotには特定のLambda関数の実行権限だけ与える ので、 先にLambdaから作ります。 サンプルなのでLambdaの内容は何でも良いのですが、 特に面白いものも思いつかなかったのでFizzBuzzです。 ChatbotをAWS CloudFormationで作成するので、こちらもそうします。 ( ドキュメント )
テンプレートはこんな感じ↓
AWSTemplateFormatVersion: 2010-09-09 Description: Dev.io Lambda Template Resources: ChatbotSampleLambda: Type: AWS::Lambda::Function Properties: Runtime: python3.7 Handler: index.lambda_handler FunctionName: chatbot-sample Code: ZipFile: | def lambda_handler(event, context): print("param: {}".format(event["num"])) result = [] for i in range(event["num"]):result.append(i%3//2*"Fizz"+i%5//4*"Buzz"or-~i) print(result) return result MemorySize: 128 Timeout: 30 Role: !GetAtt ChatbotSampleLambdaRole.Arn ChatbotSampleLambdaRole: Type: AWS::IAM::Role Properties: RoleName: !Sub chatbot-sample-lambda-role AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Principal: Service: lambda.amazonaws.com Action: sts:AssumeRole
Lambdaのテンプレート初めて書きましたが、 Code
の部分が独特に感じました…
こちらのPython3で最短と言われているFizzBuzz
を参考にしています。
Chatbotの作成
CloudFormationの部分は こちらのブログ を参考に作成しました。 ( ドキュメント )
- 初めにSlackワークスペースの登録をChatbotのコンソールから行ます。
※↑画像はすでに設定済みのものがあったため「設定済みチャンネル」が1になってまいます。 - Slackチャンネルにアプリをinviteします。
/invite @AWS
- CloudFormationでChatbotの設定を作成します。
テンプレートはこんな感じ↓AWSTemplateFormatVersion: 2010-09-09 Description: Dev.io Chatbot Template Parameters: FunctionName: Type: String TargetChannelId: Type: String TargetWorkspaceId: Type: String Resources: SampleChatbot: Type: AWS::Chatbot::SlackChannelConfiguration Properties: ConfigurationName: !Sub slack-invoke-fn-${TargetChannelId} IamRoleArn: !GetAtt SampleChatbotRole.Arn SlackWorkspaceId: !Ref TargetWorkspaceId SlackChannelId: !Ref TargetChannelId SampleChatbotRole: Type: AWS::IAM::Role Properties: RoleName: !Sub chatbot-invoke-fn-${TargetChannelId}-role AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Principal: Service: chatbot.amazonaws.com Action: sts:AssumeRole Policies: - PolicyName: chatbot-invoke-fn-policy PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Action: - lambda:invokeFunction Resource: !Sub arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:${FunctionName}
パラメータにはそれぞれ「Lambda関数名(今回は
chatbot-sample
)」「SlackワークスペースID」「SlackチャンネルID」を 指定します。
このテンプレートを使って複数SlackチャンネルのChatbotを作成した時に、リソース名がバッティングするのを避けるため、SlackチャンネルIDを設定名やロール名に含ませています。
作成した結果のChatbotのコンソール↓
実行してみる
Slackの設定したチャンネルからコマンドを発行します。(実行環境はWindows10のChromeです。)
今回であれば↓こんな感じのコマンドになります。
@aws lambda invoke --payload {"num": 20} --function-name chatbot-sample --region ap-northeast-1
--payload
がLambda関数へのパラメータ、 --function-name
が関数名です。
ちなみにリージョン名の --region
は覚えてくれるので2回目からは省略可能だそうです。
確認されるのでYesを選択します。
実行されました。
ちょっとコマンド覚えるのしんどいですよね…
(私のPCはWindows10なので、 [Win]+[V]
のクリップボード履歴でピン留めで良いかとも思ったのですが、)
社内からSlackワークフローが使えるとのアドバイスをもらったので
次章からそちらで入力の簡略化をしていきます。
(本題と全く関係無いですが、 こちらのブログ
で3位に輝いたチャンネルで教えてもらいました。)
余談(Chatbotの返信の内容について)
Lambda関数のランタイムがPython3.7だと、
print()
した内容はChatbotからの返信には含まれず
return
した内容だけが Payload
としてSlack上から確認できました。
(Node.js12でも試しましたが、
console.log()
の内容は返信されませんでした。)
たまたま気づいたのですが、カスタムランタイムで echo
すると、
実行したechoが全てPayloadに含まれていました。
また、今回のサンプルコードで、Lambda関数内でエラーが発生した場合は、
↓のように返信のPayloadがエラー内容になっていました。
Slackワークフローの作成
Slackワークフロー
では、入力フォームの利用やチャンネルへ投稿ができるので、
Chatbotコマンド入力の簡略化に使えそうです。
- トリガーのステップを作成します。
- フォームのステップを作成します。
今回のLambda関数はパラメータが1つなので、質問も1つ作ります。
- チャンネルへのChatbotコマンドの投稿のステップを
作成します。
変数を使って、前手順のフォームの値をコマンドの雛形に埋め込みます。
ここで送信先を間違うと、恥ずかしかったりChatbotに無視されて寂しかったりになると思います。
上記のワークフローを公開すると、↓ショートカットに追加されるので、
フォームに答えると、
ワークフローがコマンドを投稿してくれて、Chatbotが起動してくれます。
おわりに
ワークフローがすごく便利ですね。
Chatbotからの返信はSNSトピック経由でも良かったかもしれません。(きれいに表示されそう。)
参考文献
- Running AWS commands from Slack using AWS Chatbot
→ベータ版の時点の記事ですが、分かりやすかったです。